﻿using com.youzu.got.protocol;
using System.Collections.Generic;
using com.youzu.warh.protocol;
using UnityEngine;
using UnityEngine.Profiling;
using WorldMapBase.Tile.Pool;
using Yoozoo.Gameplay.RTS.Proto;
using Yoozoo.Mars.Got;
using Random = UnityEngine.Random;
using SiegeFightInfo = com.youzu.warh.protocol.SiegeFightInfo;
using TroopFightInfo = com.youzu.warh.protocol.TroopFightInfo;
using CastSkill = com.youzu.warh.protocol.CastSkill;
using TargetCoordinateType = Yoozoo.Gameplay.RTS.Proto.TargetCoordinateType;

namespace Yoozoo.Gameplay.RTS
{
    public partial class RoundFightPlayer
    {
        public static RoundFightPlayer Inst;
        private float heroSkillInterval = 0.5f;
        private List<Skill> skillList = new List<Skill>(512);
        private List<AttackHit> attackHitList = new List<AttackHit>(512);
        private List<SkillHit> skillHitList = new List<SkillHit>(128);
        private List<SkillName> skillNameList = new List<SkillName>(128);
        private MarchManager marchManager;
        public const int NORMAL_ATTACK_SKILL_ID = 100011;
        public const int NORMAL_ATTACK_ELEMENT_ID = 1000111;
        public const int DEFAULT_SUB_SKILL_ID = 139999;
//        private Dictionary<long, RoundFightFlyText> skillFlyTextTable = new Dictionary<long, RoundFightFlyText>();
        private Dictionary<com.youzu.warh.protocol.TargetCoordinateType,Dictionary<long, RoundFightFlyText>> skillFlyTextTable = new Dictionary<com.youzu.warh.protocol.TargetCoordinateType,Dictionary<long, RoundFightFlyText>>();
        private Dictionary<Troop, Dictionary<int, int>> myTroopElements = new Dictionary<Troop, Dictionary<int, int>>();
        private HashSet<Troop> curSkillTroopDict = new HashSet<Troop>();
        private Dictionary<Troop, Dictionary<int, int>> otherTroopElements = new Dictionary<Troop, Dictionary<int, int>>();
        private Dictionary<Troop, Dictionary<int, int>> iAttackOtherTroopElements = new Dictionary<Troop, Dictionary<int, int>>();
        private Dictionary<Troop, SkillHitElementList> healElements = new Dictionary<Troop, SkillHitElementList>(16);
        public const float PLAYER_SKILL_TIME = 0.16f,
                            PLAY_NORMAL_TEXT_TIME = 0.5f,
                            PLAYER_SKILL_TIME_INTERVAL = 0.2f,
                            SKILL_NAME_AHEAD_TIME = 0.26f,
                            HEAL_SKILL_TIME_INTERVAL = 0.2f;
        private List<RoundAttackEffect> attackEffectList = new List<RoundAttackEffect>();
        private RTSResourceManager _rtsResMgr;
        private Dictionary<Troop,List<DamageVec2>> _selfTroopNormalDamageDic = new Dictionary<Troop, List<DamageVec2>>(8);
        private Dictionary<Troop,List<DamageVec2>> _selfTroopPassiveDamageDic = new Dictionary<Troop, List<DamageVec2>>(8);
        private ListPool<DamageVec2> _damageVec2ListPool;
        public void Init(MarchManager marchManager, RTSResourceManager resourceManager)
        {
            Inst = this;
            this.marchManager = marchManager;
            _rtsResMgr = resourceManager;
            _damageVec2ListPool = new ListPool<DamageVec2>(8, false, 8, 1, 0);
        }

        public void RoundFight(com.youzu.warh.protocol.SCRoundFight scRoundFight)
        {
#if UNITY_EDITOR
            string s = Newtonsoft.Json.JsonConvert.SerializeObject(scRoundFight,Newtonsoft.Json.Formatting.Indented);
            Debug.Log(LogSystem.LogModule.RTS,$"scRoundFight:{s}");
            
#endif
            var fightInfo = scRoundFight.fightInfo;
            var siegeFightInfo = scRoundFight.siegeFightInfo;
            var startTime = TimeUtils.GetClientTickTime();
            iAttackOtherTroopElements.Clear();
            myTroopElements.Clear();
            otherTroopElements.Clear();
            healElements.Clear();
            _selfTroopNormalDamageDic.Clear();
            _selfTroopPassiveDamageDic.Clear();
            ParseSiegeFightInfo(scRoundFight.siegeFightInfo);
            RegisterAttackTroopEffects(fightInfo, startTime);
            //RegisterAttackCityEffects(siegeFightInfo, startTime);
            SplitFightInfoAndUpdateTroopInfo(fightInfo, startTime);
            ParseTroopFightInfo(fightInfo, startTime);
            PlaySkillFlyText(startTime);
            PlayHealFlyText(startTime);
            marchManager.OnRoundFightOver();
            foreach (var value in _selfTroopNormalDamageDic.Values)
            {
                value.Clear();
                _damageVec2ListPool.RecoverItem(value);
            }
            foreach (var value in _selfTroopPassiveDamageDic.Values)
            {
                value.Clear();
                _damageVec2ListPool.RecoverItem(value);
            }
        }

        private void ParseSiegeFightInfo(List<SiegeFightInfo> siegeFightInfo)
        {
            if (marchManager.ParseSiegeFightInfo!=null && siegeFightInfo.Count > 0)
            {
                foreach (var fightInfo in siegeFightInfo)
                {
                    var elements = fightInfo.elements;

                    if (elements != null)
                    {
                        foreach (var element in elements)
                        {
                            if (element != null)
                            {
                                if (element.amount > 0)
                                {
                                    var sourceMarch =
                                        marchManager.GetMarchEntityByIdAndType(element.source.uid, element.source.type);
                                    if (sourceMarch != null)
                                    {
                                        if (!sourceMarch.IsInBattle)
                                        {
                                            sourceMarch.IsInBattle = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                marchManager.ParseSiegeFightInfo.Action(siegeFightInfo);
            }
        }

        /// <summary>
        /// 播放治疗飘字
        /// </summary>
        /// <param name="startTime"></param>
        private void PlayHealFlyText(float startTime)
        {
            var healEnumeator = healElements.GetEnumerator();
            while (healEnumeator.MoveNext())
            {
                var troop = healEnumeator.Current.Key;
                var marchEntity = marchManager.GetMarchEntityByIdAndType(troop.Uid,troop.Type);
                var elementList = healEnumeator.Current.Value;
                if (marchEntity != null)
                {
                    var healTimeStartTime = startTime + PLAY_NORMAL_TEXT_TIME;
                    for (int i = 0; i < elementList.EffectElements.Count; i++)
                    {
                        var finalTime = healTimeStartTime + HEAL_SKILL_TIME_INTERVAL * i;
                        var element = elementList.EffectElements[i];
                        PlaySkillHitElement(marchEntity, finalTime, element, FlyTextManager.SkillHeal, false);
                    }
                }

                RTSClassPoolManager.RecoverSkillHitElementList(elementList);
            }

            healEnumeator.Dispose();
            healElements.Clear();
        }

        /// <summary>
        /// 播放技能飘字
        /// </summary>
        /// <param name="startTime"></param>
        private void PlaySkillFlyText(float startTime)
        {
            var skillNameTime = PLAYER_SKILL_TIME + startTime;
            var skillFlyTextTableEnumeator = skillFlyTextTable.GetEnumerator();
            while (skillFlyTextTableEnumeator.MoveNext())
            {
                var targetType = skillFlyTextTableEnumeator.Current.Key;
                var hashMap = skillFlyTextTableEnumeator.Current.Value;
                
                var enumeator = hashMap.GetEnumerator();
                while (enumeator.MoveNext())
                {
                    var sourceMarchId = enumeator.Current.Key;
                    var skillNameHash = enumeator.Current.Value.SkillIdHashSet;
                    var startTime2 = skillNameTime;
                    var sourceMarch = marchManager.GetMarchEntityByIdAndType(sourceMarchId,targetType);
                    if (sourceMarch != null)
                    {
                        if (sourceMarch != null)
                        {
                            var target = sourceMarch.GetBattleTarget();
                            if (target != null && target.flyTextTimeOffset > 0)
                            {
                                startTime2 = target.flyTextTimeOffset - SKILL_NAME_AHEAD_TIME + startTime;
                            }

                            foreach (var skillId in skillNameHash)
                            {
                                AddSkillNameText(skillId, sourceMarchId,targetType, startTime2);
                            }
                        }
                    }

                    var roundFightFlyText = enumeator.Current.Value;
                    RTSClassPoolManager.RecoverRoundFightFlyText(roundFightFlyText);
                }
                enumeator.Dispose();
            }
            skillFlyTextTableEnumeator.Dispose();
            skillFlyTextTable.Clear();
        }

        /// <summary>
        /// 注册攻击部队普工特效
        /// </summary>
        /// <param name="fightInfos"></param>
        /// <param name="time"></param>
        private void RegisterAttackTroopEffects(List<TroopFightInfo> fightInfos, float time)
        {
            curSkillTroopDict.Clear();
            foreach (var fightInfo in fightInfos)
            {
                var tid = fightInfo.troop.uid;
                var troopType = fightInfo.troop.type;
                var march = marchManager.GetMarchEntityByIdAndType(tid,troopType);
                if (march != null && fightInfo.elements != null)
                {
                    //设置战斗状态
                    if (fightInfo.isAttackIntent)
                    {
                        march.IsInBattle = true;
                    }
                    else
                    {
                        foreach (var skill in fightInfo.skills)
                        {
                            if (skill.skillId == NORMAL_ATTACK_SKILL_ID)
                            {
                                march.IsInBattle = true;
                            }
                        }
                    }

                    
                    if (fightInfo.isFightOver)
                    {
                        march.SetRoundFightOver();
                    }
                    /*
                    foreach (var element in fightInfo.elements)
                    {
                        int authorType = 0;
                        var type = JudgeElementType(element,ref authorType);
                        if (type == E_BattleTextType.NormalText || type == E_BattleTextType.DamageText)
                        {
                            var sourceMarch =
                                marchManager.GetMarchEntityByIdAndType(element.source.uid, element.source.type);
                            if (sourceMarch != null && sourceMarch.GetBattleTarget() == march)
                            {
                                bool canPlayEffectNum =
                                    attackEffectList.Count < RTSQualityHelper.MaxAttackEffectNum + 2 ||
                                    RTSQualityHelper.MaxAttackEffectNum == -1;
                                bool limitSelf = RTSQualityHelper.LimitSelfTroop;
                                var targetMarch =
                                    marchManager.GetMarchEntityByIdAndType(fightInfo.troop.uid, fightInfo.troop.type);
                                var isRelatedToSelf = sourceMarch.Team == 0;
                                if (targetMarch != null)
                                {
                                    isRelatedToSelf = targetMarch.Team == 0 || isRelatedToSelf;
                                }

                                if (!isRelatedToSelf)
                                {
                                    if (!RTSQualityHelper.IsShowThirdAttackEffect)
                                    {
                                        continue;
                                    }
                                }

                                if (!canPlayEffectNum)
                                {
                                    if ((march.Team == 0 || sourceMarch.Team == 0))
                                    {
                                        if (limitSelf)
                                        {
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        continue;
                                    }
                                }

                                var troop = new Troop(sourceMarch.Tid, sourceMarch.TargetCoordinateType);
                                //防止一个部队同一个特效播放多次
                                if (curSkillTroopDict.Contains(troop))
                                {
                                    continue;
                                }

                                curSkillTroopDict.Add(troop);

                                //判断需要播放什么特效
                                var effectId = 1004;
                                var beforeTime = 0.433f;
                                var count = 5;
                                var timeOffset = 0.25f;
                                var offset = 0.5f;
                                var bindOnSource = false;
                                if (sourceMarch.MarchInfo.SoldierType == 3)
                                {
                                    effectId = 1003;
                                    beforeTime = 0.5f;
                                    count = 1;
                                    timeOffset = 0;
                                    offset = 0.1f;
                                    bindOnSource = true;
                                }
                                else if (sourceMarch.MarchInfo.SoldierType == 2)
                                {
                                    effectId = 1002;
                                    beforeTime = 0.5f;
                                    count = 1;
                                    timeOffset = 0;
                                    offset = 0.1f;
                                    bindOnSource = true;
                                }
                                else if (sourceMarch.MarchInfo.SoldierType == 1)
                                {
                                    effectId = 1001;
                                    beforeTime = 0.23f;
                                    count = 1;
                                    timeOffset = 0;
                                    offset = 0.1f;
                                }

                                if (march.flyTextTimeOffset == 0)
                                {
                                    if (sourceMarch.Team == MarchHelper.TeamSelf)
                                    {
                                        march.flyTextTimeOffset = Random.Range(0, 1f) * 0.8f + 0.8f;
                                    }
                                    else
                                    {
                                        march.flyTextTimeOffset = Random.Range(0, 1f) * 0.8f + 2.2f;
                                    }
                                }

                                var startTime = time + march.flyTextTimeOffset - beforeTime;

                                var effect = RTSClassPoolManager.GetRoundAttackEffect();
                                effect.hasPlayed.Clear();
                                effect.startTimes.Clear();
                                for (int i = 0; i < count; i++)
                                {
                                    effect.startTimes.Add(startTime + Random.Range(0, 1f) * timeOffset);
                                    effect.hasPlayed.Add(false);
                                }

                                effect.startTime = startTime; // + Random.Range(0, 1f) * timeOffset;
                                effect.timeOffset = timeOffset;
                                effect.effectId = effectId;
                                effect.sourceMarchType = element.source.type;
                                effect.sourceMarchUid = element.source.uid;
                                effect.targetMarchType = fightInfo.troop.type;
                                effect.targetMarchUid = fightInfo.troop.uid;
                                effect.offset = offset;
                                effect.bindOnSource = bindOnSource;
                                effect.effectCount = count;
                                effect.isAttackCity = false;
                                attackEffectList.Add(effect);
                            }
                        }
                    }
                    */
                }
            }
        }



        /// <summary>
        /// 注册打城防时候的攻击特效
        /// </summary>
        /// <param name="siegeFightInfo"></param>
        /// <param name="time"></param>
        private void RegisterAttackCityEffects(List<SiegeFightInfo> siegeFightInfo, float time)
        {
            if (siegeFightInfo == null)
            {
                return;
            }

            curSkillTroopDict.Clear();
            foreach (var siegeFight in siegeFightInfo)
            {
                foreach (var element in siegeFight.elements)
                {
                    int authorType = 0;
                    var type = JudgeElementType(element,ref authorType);
                    if (type == E_BattleTextType.NormalText || type == E_BattleTextType.DamageText)
                    {
                        var sourceMarch =
                            marchManager.GetMarchEntityByIdAndType(element.source.uid, element.source.type);
                        if (sourceMarch != null)
                        {
                            if (attackEffectList.Count >= RTSQualityHelper.MaxAttackEffectNum + 2 &&
                                RTSQualityHelper.MaxAttackEffectNum != -1)
                            {
                                continue;
                            }

                            var troop = new Troop(sourceMarch.Tid, sourceMarch.TargetCoordinateType);
                            if (curSkillTroopDict.Contains(troop))
                            {
                                continue;
                            }

                            curSkillTroopDict.Add(troop);
                            if ((sourceMarch.Team == 0) || RTSQualityHelper.ShowAttackEffect())
                            {
                                //判断需要播放什么特效
                                var effectId = 1005;
                                var beforeTime = 0.433f;
                                var count = 1;
                                var timeOffset = 0.25f;
                                var offset = 0.5f;
                                var bindOnSource = true;

                                if (sourceMarch.flyTextTimeOffset == 0)
                                {
                                    if (sourceMarch.Team == MarchHelper.TeamSelf)
                                    {
                                        sourceMarch.flyTextTimeOffset = Random.Range(0, 1f) * 0.8f + 0.8f;
                                    }
                                    else
                                    {
                                        sourceMarch.flyTextTimeOffset = Random.Range(0, 1f) * 0.8f + 2.2f;
                                    }
                                }

                                var startTime = time + sourceMarch.flyTextTimeOffset - beforeTime;

                                var effect = RTSClassPoolManager.GetRoundAttackEffect();
                                effect.hasPlayed.Clear();
                                effect.startTimes.Clear();
                                for (int i = 0; i < count; i++)
                                {
                                    effect.startTimes.Add(startTime + Random.Range(0, 1f) * timeOffset);
                                    effect.hasPlayed.Add(false);
                                }

                                effect.startTime = startTime; // + Random.Range(0, 1f) * timeOffset;
                                effect.timeOffset = timeOffset;
                                effect.effectId = effectId;
                                effect.sourceMarchType = element.source.type;
                                effect.sourceMarchUid = element.source.uid;
                                effect.offset = offset;
                                effect.bindOnSource = bindOnSource;
                                effect.effectCount = count;
                                effect.isAttackCity = true;
                                attackEffectList.Add(effect);
                            }
                        }
                    }
                }
            }
        }
        private void UpdateAttackEffects(float time)
        {
            if (attackEffectList == null || attackEffectList.Count == 0)
            {
                return;
            }

            var i = 0;
            while (i < attackEffectList.Count)
            {
                var attackData = attackEffectList[i];
                bool isHasPlayed = true;
                for (int j = 0; j < attackData.effectCount; j++)
                {
                    isHasPlayed &= attackData.hasPlayed[j];
                }
                if (isHasPlayed && time >= attackData.startTime + 2)
                {
                    for (int j = 0; j < attackData.effects.Count; j++)
                    {
                        RTSLuaCallCSharpManager.RecoverEffectById(attackData.effectId, attackData.effects[j], attackData.isRelatedToSelf);
                    }
                    attackData.effects.Clear();
                    RTSClassPoolManager.RecoverRoundAttackEffect(attackData);
                    attackEffectList.RemoveAt(i);
                }
                else
                {
                    for (int j = 0; j < attackData.effectCount; j++)
                    {
                        if (!attackData.hasPlayed[j] && time >= attackData.startTimes[j])
                        {
                            attackData.hasPlayed[j] = true;

                            if (attackData.isAttackCity)
                            {
                                var sourceMarch = marchManager.GetMarchEntityByIdAndType(attackData.sourceMarchUid,attackData.sourceMarchType);
                                if (sourceMarch != null)
                                {
                                    if (!sourceMarch.IsReadyToRemove())
                                    {
                                        var isRelatedToSelf = sourceMarch.Team == 0;
                                        attackData.isRelatedToSelf = isRelatedToSelf;

                                        var effect = RTSLuaCallCSharpManager.GetEffectById(attackData.effectId, isRelatedToSelf);
                                        if (effect != null)
                                        {
                                            var sourcePosition = sourceMarch.Position;
                                            if (sourceMarch.MarchInfo.IsInBattleState)
                                            {
                                                if (sourceMarch.GetBattleTarget()!=null)
                                                {
                                                    SetAndPlayAttackEffect(attackData, effect, sourcePosition, sourceMarch.GetBattleTarget().Position);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                var targetMarch = marchManager.GetMarchEntityByIdAndType(attackData.targetMarchUid,attackData.targetMarchType);
                                var sourceMarch = marchManager.GetMarchEntityByIdAndType(attackData.sourceMarchUid,attackData.sourceMarchType);

                                if (targetMarch != null && sourceMarch != null)
                                {
                                    if (targetMarch.IsReadyToRemove() || sourceMarch.IsReadyToRemove())
                                    {

                                    }
                                    else
                                    {
                                        var isRelatedToSelf = targetMarch.Team == 0 || sourceMarch.Team == 0;
                                        attackData.isRelatedToSelf = isRelatedToSelf;

                                        var effect = RTSLuaCallCSharpManager.GetEffectById(attackData.effectId, isRelatedToSelf);
                                        if (effect != null)
                                        {
                                            var targetPosition = targetMarch.Position;
                                            var sourcePosition = sourceMarch.Position;
                                            if (attackData.bindOnSource)
                                            {
                                                if (sourceMarch.MarchInfo.IsInBattleState)
                                                {
                                                    SetAndPlayAttackEffect(attackData, effect, sourcePosition, targetPosition);
                                                }
                                            }
                                            else
                                            {
                                                if (targetMarch.MarchInfo.IsInBattleState)
                                                {
                                                    SetAndPlayAttackEffect(attackData, effect, sourcePosition, targetPosition);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    i = i + 1;
                }
            }
        }

        private void SetAndPlayAttackEffect(RoundAttackEffect attackData, GameObject effect, Vector3 sourcePosition, Vector3 targetPosition)
        {
            var offset = attackData.offset;
            if (attackData.bindOnSource)
            {
                effect.transform.position = sourcePosition;
            }
            else
            {
                var position = targetPosition + new Vector3(Random.Range(0, 1f) * offset - offset / 2, 0, Random.Range(0, 1f) * offset - offset / 2);
                effect.transform.position = position;
            }

            effect.transform.forward = targetPosition - sourcePosition;

            var animator = effect.GetComponentInChildren<Animator>();
            if (animator != null)
            {
                animator.Play("Play", -1, 0);
            }
            else
            {
                effect.gameObject.SetActive(false);
                effect.gameObject.SetActive(true);
            }
            attackData.effects.Add(effect);
        }
        /// <summary>
        /// 根据战斗信息拆分出攻击阵营，并且刷新部队信息
        /// </summary>
        /// <param name="fightInfo"></param>
        /// <param name="startTime"></param>
        private void SplitFightInfoAndUpdateTroopInfo(List<TroopFightInfo> fightInfo, float startTime)
        {
            var cameraManager = WorldCameraManager.GetInstance();
            
            foreach (var info in fightInfo)
            {
                var marchEntity = marchManager.GetMarchEntityByIdAndType(info.troop.uid,info.troop.type);
                if (marchEntity != null && cameraManager.InCamera(marchEntity.Position))
                {
                    marchEntity.UpdateRageHerIdx(info.rageHeroIndex);
                    bool isJustLeaveBattle = marchEntity.MarchInfo.isJustLeaveBattle;
                    if (info.skills != null && !isJustLeaveBattle)
                    {
                        foreach (var skill in info.skills)
                        {
                            int heroSkillIndex = 0;
                            if (skill.heroId != 0)
                            {
                                var target = marchEntity.GetBattleTarget();
                                bool play = true;
                            
                                bool canPlaySkill = GetSkillCurrentNum() < RTSQualityHelper.MaxSkillEffectNum || RTSQualityHelper.MaxSkillEffectNum == -1; //播放数量限制
                                bool limitSelf = RTSQualityHelper.LimitSelfTroop;
                                bool RelateSelf = marchEntity.Team == MarchHelper.TeamSelf ||
                                                  (target != null && target.Team == MarchHelper.TeamSelf);
                                //如果刚脱战，则不播
                                if ((target != null && target.MarchInfo.isJustLeaveBattle))
                                {
                                    play = false;
                                }
                                if (!canPlaySkill)
                                {
                                    if (RelateSelf)
                                    {
                                        if (limitSelf)
                                        {
                                            play = false;
                                        }
                                    }
                                    else
                                    {
                                        play = false;
                                    }
                                }

                                var playRageEffect = true;
                                if (!RelateSelf)
                                {
                                    playRageEffect = RTSQualityHelper.IsShowThirdRageEffect;
                                }
                                
                                if (play)
                                {
                                    if(marchEntity.Team == MarchHelper.TeamSelf)
                                    {
                                        var skillConfig = _rtsResMgr.GetHeroSkillConfig(skill.skillId, skill.skillLv);
                                        if (skillConfig != null && skillConfig.type == 2)
                                        {
                                            marchManager.DispatchSkillEvent?.Action(skill.skillId,skill.skillLv,skill.heroId, marchEntity.Tid,(int)marchEntity.TargetCoordinateType);
                                        }
                                    }

                                    if (playRageEffect)
                                    {
                                        AddSkill(skill, heroSkillIndex, marchEntity, startTime);
                                    }
//                                    RegistFlyTextInfo(skillFlyTextTable, skill, info.troop.uid,info.troop.type);
                                }
                                //Debug.LogError("有heroId的技能释放 " + skill.skillId);
                            }
                            else
                            {
                                //Debug.LogError("没有heroId的技能释放 " + skill.skillId);
                                //播放不需要heroId的特效(如豪车,或者装备)
                                if (skill.skillId != NORMAL_ATTACK_SKILL_ID)
                                {
                                    if (marchEntity.Team == MarchHelper.TeamSelf)
                                    {
                                        var skillConfig = _rtsResMgr.GetHeroSkillConfig(skill.skillId, skill.skillLv);
                                        if (skillConfig != null)
                                        {
                                            // author_type 1 英雄 3 豪车  type 2 怒气技能 5 被动固有
                                            // 英雄怒气技能 和 豪车技能 都要播放走马灯 by 艾德
                                            if ((skillConfig.author_type == 1 && skillConfig.type == 2) ||
                                                (skillConfig.author_type == 3 && skillConfig.type == 5))
                                            {
                                                // 通知lua 播放走马灯
                                                marchManager.DispatchSkillEvent?.Action(skill.skillId,skill.skillLv,skill.heroId, marchEntity.Tid,(int)marchEntity.TargetCoordinateType);
                                            }
                                        }
                                    }

                                    CheckNormalSkillEffect(marchEntity,skill,startTime);
                                }
                            }
                        }
                    }
                    
                    var team = marchEntity.Team;
                    if (team == MarchHelper.TeamSelf)
                    {
                        var troop = new Troop(marchEntity.RtsServerInfo.tid, marchEntity.RtsServerInfo.Type);
                        if (!myTroopElements.ContainsKey(troop))
                        {
                            myTroopElements.Add(troop,new Dictionary<int, int>());
                        }

                        if (info.normalDamage!=null) //把我造成的普攻伤害转换成以受到伤害部队为key的数据格式
                        {
                            foreach (var damage in info.normalDamage)
                            {
                                var targetTroop = new Troop(damage.target.uid, damage.target.type);
                                if (!_selfTroopNormalDamageDic.TryGetValue(targetTroop,out var list))
                                {
                                    list = _damageVec2ListPool.GetItem();
                                    _selfTroopNormalDamageDic.Add(targetTroop,list);
                                }
                                list.Add(new DamageVec2(info.troop.uid,damage.damage)); 
                            }
                        }
                        
                        if (info.passiveDamage!=null)//把我造成的被动伤害转换成以受到伤害部队为key的数据格式
                        {
                            foreach (var damage in info.passiveDamage)
                            {
                                var targetTroop = new Troop(damage.target.uid, damage.target.type);
                                if (!_selfTroopPassiveDamageDic.TryGetValue(targetTroop,out var list))
                                {
                                    list = _damageVec2ListPool.GetItem();
                                    _selfTroopPassiveDamageDic.Add(targetTroop,list);
                                }
                                list.Add(new DamageVec2(info.troop.uid,damage.damage)); 
                            }
                        }
                        
                    }
                    else
                    {
                        var elements = info.elements;
                        if (elements != null)
                        {
                            foreach (var element in elements)
                            {
                                var sourceMarchId = element.source.uid;
                                var sourceMarch =
                                    marchManager.GetMarchEntityByIdAndType(sourceMarchId, element.source.type);
                                if (sourceMarch != null)
                                {
                                    var troop = new Troop(info.troop.uid, (TargetCoordinateType) info.troop.type);
                                    if (sourceMarch.Team == MarchHelper.TeamSelf)
                                    {
                                        if (!iAttackOtherTroopElements.ContainsKey(troop))
                                        {
                                            iAttackOtherTroopElements.Add(troop, new Dictionary<int, int>());
                                        }
                                    }
                                    else
                                    {
                                        if (!otherTroopElements.ContainsKey(troop))
                                        {
                                            otherTroopElements.Add(troop, new Dictionary<int, int>());
                                        }
                                    }
                                }
                            }
                        }
                    }
                    int costRage = CalSkillRageCost(info.skills);
                    if (!isJustLeaveBattle)
                    {
                        if (marchEntity.isFakeParent &&
                            marchEntity.GetFakeChildEntities() is List<MarchEntity> entities)
                        {
                            for (int i = 0; i < entities.Count; i++)
                            {
                                entities[i].RoundFight(info.rage, info.curSoldierNum,info.intSoldierNum, marchEntity.IsInBattle, costRage);
                                entities[i].UpdateRageHerIdx(info.rageHeroIndex);
                            }
                        }
                        else
                        {
                            marchEntity.RoundFight(info.rage, info.curSoldierNum,info.intSoldierNum, marchEntity.IsInBattle, costRage);
                            marchEntity.UpdateRageHerIdx(info.rageHeroIndex);
                        }
                    }
                    PlayDeadFlyText(info,marchEntity);
                    Profiler.BeginSample("DispatchSoldierCount");
                    DispatchSoldierCount(info,marchEntity);
                    Profiler.EndSample();
                }
            }
        }

        private const string ui_trooplist_29 = "ui_trooplist_29";
        private const string ui_trooplist_27 = "ui_trooplist_27";

        private void PlayDeadFlyText(TroopFightInfo info, MarchEntity marchEntity)
        {
            if (info.curSoldierNum == 0) //如果部队死亡播放死亡飘字
            {
                bool playText = marchEntity.ClientMarchType == EClientMarchType.March ||  marchEntity.ClientMarchType == EClientMarchType.Monster;
                var attackMarch = marchEntity.GetBattleTarget();
                bool isPveAssemblyTarget = MarchHelper.IsPveAssembleTarget(marchEntity);
                bool isPveAssemblyTargetAttacker = attackMarch != null && MarchHelper.IsPveAssembleTarget(attackMarch);
                if (isPveAssemblyTarget)//警察署死了，播放胜利
                {
                    var position = marchEntity.Position;
                    if (attackMarch != null)
                    {
                        position = attackMarch.Position;
                        attackMarch.SetIsPveBattleWin(true);
                    }
                    RTSLuaCallCSharpManager.FlyText(FlyTextManager.Route, position, _rtsResMgr.GetLangConfigTxt(ui_trooplist_27), 1, default, default, 0);
                }
                else if (isPveAssemblyTargetAttacker)//打警察署的死了，播放失败
                {
                    RTSLuaCallCSharpManager.FlyText(FlyTextManager.Failed, marchEntity.Position, _rtsResMgr.GetLangConfigTxt(ui_trooplist_29), 1, default, default, 0);
                }
                else if (playText)
                {
                    var position = marchEntity.Position;
                    var txt = ui_trooplist_29; //_rtsResMgr.GetLangConfigTxt(ui_trooplist_29);
                    var id = FlyTextManager.Failed;
                    
                    if (marchEntity.Team == (int) MarchTeam.Self) //自己部队死了播放Defeat
                    {
                        RTSLuaCallCSharpManager.FlyText(id, position, _rtsResMgr.GetLangConfigTxt(txt), 1, default, default, 0);
                    }
                    else
                    {
                        foreach (var element in info.elements)
                        {
                            var tid = element.source.uid;
                            var attackMarchObject = marchManager.GetMarchEntityByIdAndType(tid, element.source.type);
                            if (attackMarchObject != null)
                            {
                                if (attackMarchObject.Team == (int) MarchTeam.Self)
                                {
                                    txt = ui_trooplist_27;
                                    id = FlyTextManager.Route;
                                    RTSLuaCallCSharpManager.FlyText(id, attackMarchObject.Position,
                                        _rtsResMgr.GetLangConfigTxt(txt), 1, default, default, 0);
                                }
                            }
                        }
                        //如果是医药公司的野怪，播放骷髅
                        if (marchEntity.ClientMarchType == EClientMarchType.Monster)
                        {
                            var npcType = marchEntity.RtsServerInfo.npcConfigType;
                            if (npcType  >= 14 && npcType  <= 21 && npcType  != 16)
                            {
                                RTSLuaCallCSharpManager.FlyText(FlyTextManager.MonsterDead, marchEntity.Position,
                                    string.Empty, 1, default, default, 0);
                            }
                        }
                    }
                }
            }
        }
        private UpdateSoldierStruct soldierCountStruct = new UpdateSoldierStruct();
        private void DispatchSoldierCount(TroopFightInfo info, MarchEntity marchEntity)
        {
            // 添加判断条件 如果在联盟建筑中的战斗部队也向lua更新
            bool fightInAllianceBuild = (marchEntity.RtsServerInfo.buildType == TargetCoordinateType.ALLIANCE_CASTLE_10 ||
                    marchEntity.RtsServerInfo.buildType == TargetCoordinateType.ALLIANCE_FLAG_11) && marchEntity.IsInBattle;
            var needDispatch = marchEntity.Team == MarchHelper.TeamSelf ||
                               marchEntity.RtsServerInfo.Type == TargetCoordinateType.ALLIANCE_PRACTICE_BOSS_32 ||
                               marchEntity.RtsServerInfo.Type == TargetCoordinateType.DONALD_BOSS_38 ||
                               marchEntity.isExpeditionMarch || fightInAllianceBuild;
            if (MarchManager.UpdateSoldierCallBack!=null && (needDispatch))
            {
                soldierCountStruct.Tid = info.troop.uid;
                soldierCountStruct.Type = (int)marchEntity.RtsServerInfo.Type;
                soldierCountStruct.InitSoldierCount = info.intSoldierNum;
                soldierCountStruct.SoldierCount = info.curSoldierNum;
                MarchManager.UpdateSoldierCallBack(soldierCountStruct);
            }
        }

        
        /// <summary>
        /// 解析战斗信息
        /// </summary>
        /// <param name="fightInfo"></param>
        /// <param name="startTime"></param>
        private void ParseTroopFightInfo(List<TroopFightInfo> fightInfo, float startTime)
        {
            foreach (var info in fightInfo)
            {
                var tid = info.troop.uid;
                var marchEntity = marchManager.GetMarchEntityByIdAndType(tid,info.troop.type);
                if (marchEntity != null)
                {
                    if (marchEntity.isFakeParent && marchEntity.GetFakeChildEntities() is List<MarchEntity> fakeChildEntities)
                    {
                        for (int i = 0; i < fakeChildEntities.Count; i++)
                        {
                            var march = fakeChildEntities[i];
                            ParseTroopFightInfoToMarchEntity(info, march, startTime);
                        }
                    }
                    else
                    {
                        ParseTroopFightInfoToMarchEntity(info, marchEntity, startTime);
                    }
                }
            }

            if (buildingAttackHitMap.Count > 0)
            {
                foreach (var keyValuePair in buildingAttackHitMap)
                {
                    AddAttackHit(keyValuePair.Value);
                    RTSClassPoolManager.RecoverAttackHitTemp(keyValuePair.Value);
                }
                buildingAttackHitMap.Clear();
            }
        }

        private void ParseTroopFightInfoToMarchEntity(TroopFightInfo info, MarchEntity marchEntity, float startTime)
        {
            var tid = info.troop.uid;
            var troop = new Troop(tid, (TargetCoordinateType) info.troop.type);
            if (iAttackOtherTroopElements.ContainsKey(troop)) //我攻击的目标
            {
                var otherTroopElements1 = iAttackOtherTroopElements[troop];
                if (marchEntity != null && info.elements != null)
                {
                    foreach (var element in info.elements)
                    {
                        int authorType = 0;
                        var type = JudgeElementType(element,ref authorType);
                        
                        //普攻和固有技能合并成一个数字
                        if (type == E_BattleTextType.NormalText)
                        {
                            var sourceMarch =
                                marchManager.GetMarchEntityByIdAndType(element.source.uid, element.source.type);
                            if (sourceMarch != null)
                            {
                                CombineElementData(otherTroopElements1, element, MarchHelper.TeamSelf);
                            }

                            if (element.elementId != NORMAL_ATTACK_ELEMENT_ID)
                            {
                                AddSkillText(element, skillFlyTextTable);
                            }
                        }
                        else if (type == E_BattleTextType.HealText) //治疗
                        {
                            var healTimeStartTime = startTime;
                            if (ElementIsInherentSkill(element))
                            {
                                healTimeStartTime = startTime + PLAY_NORMAL_TEXT_TIME;
                                AddSkillText(element, skillFlyTextTable);
                                AddHealElements(troop, element);
                            }
                            else
                            {
                                PlaySkillHitElement(marchEntity, healTimeStartTime, element, FlyTextManager.SkillHeal);
                            }
                        }
                        else //怒气伤害
                        {
                            PlaySkillHitElement(marchEntity, startTime, element, FlyTextManager.Skill);
                        }
                    }

                    if (otherTroopElements1.ContainsKey(MarchHelper.TeamSelf))
                    {
                        var selfNormalDamage = 0;
                        if (_selfTroopNormalDamageDic.TryGetValue(troop,out var list1))
                        {
                            foreach (var damageVec2 in list1)
                            {
                                selfNormalDamage += damageVec2.damage;
                            }
                        }

                        var selfPossiveDamage = 0;
                        if (_selfTroopPassiveDamageDic.TryGetValue(troop, out var list2))
                        {
                            foreach (var damageVec2 in list2)
                            {
                                selfPossiveDamage += damageVec2.damage;
                            }
                        }

                        var otherHitAmount = otherTroopElements1[MarchHelper.TeamSelf] - selfNormalDamage -
                                             selfPossiveDamage;
                        if (otherHitAmount > 0)
                        {
                            AddAttackHitElement(
                                -(otherHitAmount),
                            marchEntity, startTime,
                            FlyTextManager.NormalAttackOther); 
                        }
                        
                        if (selfNormalDamage > 0)
                        {
                            AddAttackHitElement(-selfNormalDamage, marchEntity, startTime,
                                FlyTextManager.NormalAttackEnemy);
                        }

                        if (selfPossiveDamage > 0)
                        {
                            AddAttackHitElement(-selfPossiveDamage, marchEntity, startTime + PLAYER_SKILL_TIME,
                                FlyTextManager.PassiveAttack);
                        }
                    }
                    
                }
            }
            else if (myTroopElements.ContainsKey(troop))
            {
                var myElements = myTroopElements[troop];
                if (marchEntity != null && info.elements != null)
                {
                    foreach (var element in info.elements)
                    {
                        int authorType = 0;
                        var type = JudgeElementType(element,ref authorType);

                        if (type == E_BattleTextType.NormalText)
                        {
                            CombineElementData(myElements, element, MarchHelper.TeamEnemy);

                            if (element.elementId != NORMAL_ATTACK_ELEMENT_ID)
                            {
                                AddSkillText(element, skillFlyTextTable);
                            }
                            
                            if (authorType == (int)SkillAuthorType.CarSkill)
                            {
                                CheckPlayCarSkillElementEffect(marchEntity,startTime,element);
                            }
                        }
                        else if (type == E_BattleTextType.HealText)
                        {
                            var healTimeStartTime = startTime;
                            if (ElementIsInherentSkill(element))
                            {
                                healTimeStartTime = startTime + PLAY_NORMAL_TEXT_TIME;
                                AddSkillText(element, skillFlyTextTable);
                                AddHealElements(troop, element);
                            }
                            else
                            {
                                PlaySkillHitElement(marchEntity, healTimeStartTime, element, FlyTextManager.SkillHeal);
                            }
                        }
                        else
                        {
                            //技能类 拆分显示
                            PlaySkillHitElement(marchEntity, startTime, element, FlyTextManager.SkillSelf);
                        }
                    }

                    if (myElements.TryGetValue(MarchHelper.TeamEnemy, out var amount))
                    {
                        AddAttackHitElement(-amount, marchEntity, startTime, FlyTextManager.NormalAttackSelf);
                    }
                }
            }
            else
            {
                //与我无关的只显示普通形式的飘字
                if (marchEntity != null && info.elements != null)
                {
                    int amount = 0;
                    foreach (var element in info.elements)
                    {

                        int elementId = element.elementId;
                        var elementConfig = _rtsResMgr.GetSkillElementRtsConfig(elementId);
                        var elementType = 1;
                        if (elementConfig != null)
                        {
                            elementType = elementConfig.element_type;
                        }
                        int authorType = 0;
                        var type = JudgeElementType(element,ref authorType);
                        if (type == E_BattleTextType.DamageText)
                        {
                            PlaySkillHitElement(marchEntity, startTime, element, FlyTextManager.Skill);
                        } 
                        else if (type == E_BattleTextType.HealText) //治疗
                        {
                            var healTimeStartTime = startTime;
                            if (ElementIsInherentSkill(element))
                            {
                                healTimeStartTime = startTime + PLAY_NORMAL_TEXT_TIME;
                                AddSkillText(element, skillFlyTextTable);
                                AddHealElements(troop, element);
                            }
                            else
                            {
                                PlaySkillHitElement(marchEntity, healTimeStartTime, element, FlyTextManager.SkillHeal);
                            }
                        }
                        else
                        {
                            if (elementType == 9)
                            {
                                amount += element.amount;
                            }
                            else
                            {
                                amount -= element.amount;
                            }
                        }
                       
                    }

                    if (RTSQualityHelper.IsShowThirdNormalText)
                    {
                        AddAttackHitElement(amount, marchEntity, startTime, FlyTextManager.NormalAttackOther);
                    }
                }
            }
        }

        /// <summary>
        /// 非怒气技能的治疗元素加入列表里，等待间隔一个个播放
        /// </summary>
        /// <param name="tid"></param>
        /// <param name="element"></param>
        private void AddHealElements(Troop troop,com.youzu.warh.protocol.EffectElement element)
        {
            if (healElements.TryGetValue(troop, out SkillHitElementList list))
            {
                list.AddElement(element);
            }
            else
            {
                list = RTSClassPoolManager.GetSkillHitElementList();
                list.AddElement(element);
                healElements.Add(troop, list);
            }
        }
        private int CalSkillRageCost(List<CastSkill> skills)
        {
            if (skills == null)
            {
                return 0;
            }
            var costRage = 0;
            foreach (var skill in skills)
            {
                if (skill.skillId != NORMAL_ATTACK_SKILL_ID)
                {
                    var skillCfg = _rtsResMgr.GetHeroSkillConfig(skill.skillId, skill.skillLv);
                    if (skillCfg != null && skillCfg.type == 2)
                    {
                        costRage += skillCfg.mana;
                    }
                }
            }

            return costRage;
        }
        private Dictionary<long, AttackHitTemp> buildingAttackHitMap = new Dictionary<long, AttackHitTemp>();

        private void AddAttackHitElement(int amount, MarchEntity marchEntity, float startTime, int textType)
        {
            if (marchEntity.MarchInfo.BuildingUid != 0)
            {
                if (buildingAttackHitMap.TryGetValue(marchEntity.MarchInfo.BuildingUid, out AttackHitTemp hitTemp))
                {
                    hitTemp.Amount += amount;
                }
                else
                {
                    var attackHitTemp = RTSClassPoolManager.GetAttackHitTemp();
                    attackHitTemp.Amount = amount;
                    attackHitTemp.StartTime = startTime;
                    attackHitTemp.TextType = textType;
                    attackHitTemp.Position = marchEntity.Position;

                    // 显示建筑中伤害飘字 需要判断是自己造成的伤害 不然会显示太多 -20241125 艾de
                    MarchEntity target = marchEntity.GetBattleTarget();
                    if (target != null && target.MarchInfo.Team == (int)MarchTeam.Self)
                    { 
                        buildingAttackHitMap.Add(marchEntity.MarchInfo.BuildingUid, attackHitTemp);
                    }
                }
                marchEntity.UpdateHudHpPercent();
            }
            else
            {
                var time = marchEntity.flyTextTimeOffset != 0 ? marchEntity.flyTextTimeOffset : PLAY_NORMAL_TEXT_TIME;
                startTime = startTime + time;
                AddAttackHit(amount, startTime, textType, marchEntity, marchEntity.GetBattleTarget());
            }
        }
        

        private void PlaySkillHitElement(MarchEntity marchEntity, float startTime,
            com.youzu.warh.protocol.EffectElement element, int textType, bool useSourceTime = true)
        {
            if (useSourceTime)
            {
                var sourceTime = GetSkillStartTime(element.skillId, element.skillLv, element.source.uid);
                if (sourceTime > 0)
                {
                    startTime = sourceTime;
                }
            }

            if (element.source.uid != 0)
            {
                AddFlyTextHitElement(element, startTime, marchEntity, textType);
            }
        }

        private bool ElementIsInherentSkill(com.youzu.warh.protocol.EffectElement element)
        {
            var skillId = element.skillId;
            var skillLv = element.skillLv;
            var elementId = element.elementId;
            var config = _rtsResMgr.GetHeroSkillConfig(skillId, skillLv);
            if (config != null)
            {
                var skillType = config.type;
                return skillType == 4 || skillType == 5 || skillType == 6 || skillType == 7;
            }
            else
            {
                return false;
            }

        }

        private void AddSkillText(com.youzu.warh.protocol.EffectElement element,
            Dictionary<com.youzu.warh.protocol.TargetCoordinateType, Dictionary<long, RoundFightFlyText>>
                skillFlyTextTable)
        {
            var config = _rtsResMgr.GetHeroSkillConfig(element.skillId, element.skillLv);
            if (config.author_type != 3)
            {
                RegistFlyTextInfo(skillFlyTextTable, element.skillId, element.source.uid, element.source.type);
            }
        }

        private void CombineElementData(Dictionary<int, int> troopElements, com.youzu.warh.protocol.EffectElement element, int team)
        {
            int amount = element.amount;

            if (!troopElements.ContainsKey(team))
            {
                troopElements[team] = amount;
            }
            else
            {
                troopElements[team] += amount;
            }

        }

        private E_BattleTextType JudgeElementType(com.youzu.warh.protocol.EffectElement element,ref int authorType)
        {
            var skillId = element.skillId;
            var skillLv = element.skillLv;
            var elementId = element.elementId;
            int skillType = 1;
            var skillConfig = _rtsResMgr.GetHeroSkillConfig(skillId, skillLv);
            authorType = 1;
            if (skillConfig != null)
            {
                skillType = skillConfig.type;
                authorType = skillConfig.author_type;
            }

            int elementType = 1;
            var elementConfig = _rtsResMgr.GetSkillElementRtsConfig(elementId);
            if (elementConfig != null)
            {
                elementType = elementConfig.element_type;
            }

            // 豪车技能不合并 authorType == 3
            // 1.普通攻击
            // 2.怒气技能
            // 3.预留站位
            // 4.指挥固有
            // 5.被动固有
            // 6.自发固有
            // 7.追击固有
            if ((skillType == 1 || skillType == 4 || skillType == 5 || skillType == 6 || skillType == 7) && elementType != 9 && authorType != 3)
            {
                return E_BattleTextType.NormalText;
            }
            else if (elementType == 9)
            {
                return E_BattleTextType.HealText;
            }
            else
            {
                return E_BattleTextType.DamageText;
            }
        }

        private void RegistFlyTextInfo(Dictionary<com.youzu.warh.protocol.TargetCoordinateType,Dictionary<long, RoundFightFlyText>> hasAddSkillFlyTextTable, CastSkill skill, long tid,com.youzu.warh.protocol.TargetCoordinateType type)
        {
            if (!hasAddSkillFlyTextTable.TryGetValue(type,out var hashMap))
            {
                hashMap = new Dictionary<long, RoundFightFlyText>();
                hasAddSkillFlyTextTable.Add(type,hashMap);
            }
            
            if (!hashMap.TryGetValue(tid, out RoundFightFlyText flyTextInfo))
            {
                flyTextInfo = RTSClassPoolManager.GetRoundFightFlyText();
                flyTextInfo.sourceMarchTid = tid;
                hashMap.Add(tid, flyTextInfo);
            }
            flyTextInfo.SkillIdHashSet.Add(skill.skillId);
        }
        private void RegistFlyTextInfo(Dictionary<com.youzu.warh.protocol.TargetCoordinateType,Dictionary<long, RoundFightFlyText>> hasAddSkillFlyTextTable, int skillId, long tid,com.youzu.warh.protocol.TargetCoordinateType targetType)
        {
            if (!hasAddSkillFlyTextTable.TryGetValue(targetType,out var hashMap))
            {
                hashMap = new Dictionary<long, RoundFightFlyText>();
                hasAddSkillFlyTextTable.Add(targetType, hashMap);
            }
            
            if (!hashMap.TryGetValue(tid, out RoundFightFlyText flyTextInfo))
            {
                flyTextInfo = RTSClassPoolManager.GetRoundFightFlyText();
                flyTextInfo.sourceMarchTid = tid;
                hashMap.Add(tid, flyTextInfo);
            }
            flyTextInfo.SkillIdHashSet.Add(skillId);
        }
        public void Update(float time)
        {
            int index = 0;
            while (index < skillList.Count)
            {
                var skill = skillList[index];
                skill.Update(time);
                if (skill.IsEnd())
                {
                    var delete = skillList[index];
                    int lastIndex = skillList.Count - 1;
                    var last = skillList[skillList.Count - 1];
                    skillList[index] = last;
                    RTSClassPoolManager.RecoverSkill(delete);
                    skillList.RemoveAt(lastIndex);
                    delete.Dispose();
                }
                else
                {
                    index++;
                }
            }

            index = 0;

            while (index < attackHitList.Count)
            {
                var attackHit = attackHitList[index];
                attackHit.Update(time);
                if (attackHit.IsEnd())
                {
                    var delete = attackHitList[index];
                    int lastIndex = attackHitList.Count - 1;
                    var last = attackHitList[attackHitList.Count - 1];
                    attackHitList[index] = last;
                    RTSClassPoolManager.RecoverAttackHit(delete);
                    attackHitList.RemoveAt(lastIndex);
                    delete.Dispose();
                }
                else
                {
                    index++;
                }
            }

            index = 0;

            while (index < skillHitList.Count)
            {
                var skillHit = skillHitList[index];
                skillHit.Update(time);
                if (skillHit.IsEnd())
                {
                    var delete = skillHitList[index];
                    int lastIndex = skillHitList.Count - 1;
                    var last = skillHitList[skillHitList.Count - 1];
                    skillHitList[index] = last;
                    RTSClassPoolManager.RecoverSkillHit(delete);
                    skillHitList.RemoveAt(lastIndex);
                    delete.Dispose();
                }
                else
                {
                    index++;
                }
            }

            index = 0;

            while (index < skillNameList.Count)
            {
                var skillName = skillNameList[index];
                skillName.Update(time);
                if (skillName.IsEnd())
                {
                    var delete = skillNameList[index];
                    int lastIndex = skillNameList.Count - 1;
                    var last = skillNameList[skillNameList.Count - 1];
                    skillNameList[index] = last;
                    RTSClassPoolManager.RecoverSkillName(delete);
                    skillNameList.RemoveAt(lastIndex);
                    delete.Dispose();
                }
                else
                {
                    index++;
                }
            }

//            UpdateAttackEffects(time);
            UpdateDirectionEffect();
        }

        internal void AddSkill(CastSkill skill, int heroSkillIndex, MarchEntity marchEntity, float startTime)
        {
            if (skill.target == null)
            {
                Debug.LogError("skill.target为空 id = " + skill.skillId);
                return;
            }
            var skillCls = RTSClassPoolManager.GetSkill();
            var skillTime = startTime + PLAYER_SKILL_TIME;
            startTime = skillTime + heroSkillIndex * heroSkillInterval;

            skillCls.Initialize(skill, heroSkillIndex, marchEntity, startTime);
            skillList.Add(skillCls);
        }

        public int GetSkillCurrentNum()
        {
            return skillList.Count;
        }

        public float GetSkillStartTime(int skillId, int skillLv, long tid)
        {
            foreach (var skill in skillList)
            {
                if (skill.March != null && skill.CheckIsSame(skillId, skillLv) && skill.March.Tid == tid)
                {
                    return skill.GetStartTime();
                }
            }
            return 0;
        }

        public void AddFlyTextHitElement(com.youzu.warh.protocol.EffectElement element, float startTime, MarchEntity march, int textType)
        {
            var elementConfig = ArmyManager.Instance.ResourceManager.GetSkillElementRtsConfig(element.elementId);
            if (elementConfig != null)
            {
                if (elementConfig.float_text_type != 1)
                {
                    if (elementConfig.float_text_type < 100)
                    {
                        var skillHit = RTSClassPoolManager.GetSkillHit();
                        skillHit.Initialize(element, march, startTime, march.GetBattleTarget(), textType);
                        skillHitList.Add(skillHit);
                    }
                }
            }
        }



        internal void AddAttackHit(int amount, float startTime, int textType, MarchEntity march, MarchEntity target)
        {
            var attackHitItem = RTSClassPoolManager.GetAttackHit();
            attackHitItem.Initialize(march, amount, startTime, target, textType);
            attackHitList.Add(attackHitItem);
        }
        internal void AddAttackHit(AttackHitTemp hitTemp)
        {
            var attackHitItem = RTSClassPoolManager.GetAttackHit();
            attackHitItem.Initialize(hitTemp);
            attackHitList.Add(attackHitItem);
        }
        internal void AddSkillNameText(int skillId, long fromTid,com.youzu.warh.protocol.TargetCoordinateType targetType, float startTime)
        {
            var skillName = RTSClassPoolManager.GetSkillName();
            int queue = 0;
            for (int i = 0; i < skillNameList.Count; i++)
            {
                var skillNameCls = skillNameList[i];
                if (fromTid == skillNameCls.fromTid && skillNameCls.status == ERtsSkillState.NotPlay)
                {
                    queue = queue + 1;
                }
            }
            skillName.Initialize(skillId, fromTid,targetType, startTime, queue);
            skillName.delayArg = queue;
            skillNameList.Add(skillName);
        }

        private List<MarchEntity> _haveDirectionEffectEntityList = new List<MarchEntity>();
        private Dictionary<long, int> _Uid2IndexMap = new Dictionary<long, int>();

        internal void AddDirectionEffect(long uid,TargetCoordinateType type, MarchEntity entity, bool isMeAttack = false)
        {
            bool isDefence = entity.MarchInfo.MarchType == MarchType.DEFENCE_6;
            if (!_Uid2IndexMap.ContainsKey(uid) && entity.MarchInfo.BuildingUid == 0 && !isDefence && marchManager.marchContext.MarchLodLevel < WorldEntry.MaxShowMarchLodLevel)
            {
                bool isSelfTeam = entity.Team == (int)MarchTeam.Self;
                bool isAttackSelfTeam = false;
                if (!isSelfTeam)
                {
                    var target = entity.GetBattleTarget();
                    if (target != null)
                    {
                        isAttackSelfTeam = target.Team == (int)MarchTeam.Self;
                    }
                }

                if (isSelfTeam || isAttackSelfTeam || isMeAttack)
                {
                    var length = _haveDirectionEffectEntityList.Count;
                    _haveDirectionEffectEntityList.Add(entity);
                    _Uid2IndexMap.Add(uid, length);
                    AddEffect(uid,type,entity);
                }

            }
        }

        internal void RemoveDirectionEffect(long uid)
        {
            if (_Uid2IndexMap.TryGetValue(uid, out int index))
            {
                MarchEntity removeElement;
                if (index == _haveDirectionEffectEntityList.Count - 1)
                {
                    removeElement = _haveDirectionEffectEntityList[index];
                    _Uid2IndexMap.Remove(uid);
                    _haveDirectionEffectEntityList.RemoveAt(index);
                }
                else
                {
                    var lastIndex = _haveDirectionEffectEntityList.Count - 1;
                    removeElement = _haveDirectionEffectEntityList[index];
                    var final = _haveDirectionEffectEntityList[lastIndex];

                    _haveDirectionEffectEntityList[index] = final;

                    _Uid2IndexMap[final.MarchInfo.Uid] = index;

                    _haveDirectionEffectEntityList.RemoveAt(lastIndex);
                    _Uid2IndexMap.Remove(uid);
                }

                if (removeElement != null)
                {
                    if (removeElement.DirectionEffectObj != null)
                    {
                        var animator = removeElement.DirectionEffectObj.GetComponent<Animator>();
                        if (animator != null)
                        {
                            if (removeElement.DirectionEffectType == DirectionEffectType.Direction)
                            {
                                animator.SetTrigger("SemiCircleFadeOut");
                            }
                            else
                            {
                                animator.SetTrigger("CircleFadeOut");
                            }
                        }
                        Timers.inst.Add(0.2f, 1, (o) =>
                        {
                            if (removeElement.DirectionEffectObj != null)
                            {
                                RTSLuaCallCSharpManager.RecoverResourceById(806, removeElement.DirectionEffectObj);
                                foreach (var parameter in animator.parameters)
                                {
                                    animator.ResetTrigger(parameter.name);
                                }
                                removeElement.DirectionEffectObj = null;
                                removeElement.DirectionEffectType = DirectionEffectType.None;
                            }
                        });
                    }
                }
            }
        }

        public void OnChangedEffect(long id,TargetCoordinateType type)
        {
            if (_Uid2IndexMap.TryGetValue(id, out int index))
            {
                var entity = _haveDirectionEffectEntityList[index];
                AddEffect(id,type,entity);
            }
        }
        private void AddEffect(long id,TargetCoordinateType type, MarchEntity entity)
        {
            DirectionEffectType effectType = DirectionEffectType.None;
            var attackerCount = marchManager.GetPlayerAttackerCount(id,type);
            var marchTarget = entity.GetTarget();
            var battleTarget = entity.GetBattleTarget();


            if (marchTarget == null && entity.IsMoving())
            {
                effectType = DirectionEffectType.WithoutDirection;
            }
            else
            {
                if (battleTarget != null)
                {
                    if (attackerCount > 1)
                    {
                        effectType = DirectionEffectType.WithoutDirection;
                    }
                    else
                    {
                        if (marchTarget == null && entity.IsMoving())
                        {
                            effectType = DirectionEffectType.WithoutDirection;
                        }
                        else
                        {
                            effectType = DirectionEffectType.Direction;
                        }
                    }
                }
            }


            if (entity.DirectionEffectType == DirectionEffectType.None) //创建
            {
                var effect = RTSLuaCallCSharpManager.GetResourceById(806);
                if (!effect.activeInHierarchy)
                {
                    effect.SetActive(true);
                }
                entity.DirectionEffectObj = effect;
                entity.DirectionEffectType = effectType;
                var animator = effect.GetComponent<Animator>();
                if (animator != null)
                {
                    if (effectType == DirectionEffectType.Direction)
                    {
                        animator.SetTrigger("SemiCircleFadeIn");
                    }
                    else
                    {
                        animator.SetTrigger("CircleFadeIn");
                    }
                }
                SetEffectColor(effect, entity.Team);
            }
            else
            {
                if (effectType != DirectionEffectType.None)
                {
                    if (entity.DirectionEffectType != effectType)//变换
                    {
                        if (entity.DirectionEffectObj != null)
                        {
                            SetEffectColor(entity.DirectionEffectObj, entity.Team);

                            var animator = entity.DirectionEffectObj.GetComponent<Animator>();
                            if (animator != null)
                            {
                                if (effectType == DirectionEffectType.Direction && entity.DirectionEffectType == DirectionEffectType.WithoutDirection)
                                {
                                    animator.SetTrigger("CircleToSemiCircle");
                                }
                                if (effectType == DirectionEffectType.WithoutDirection && entity.DirectionEffectType == DirectionEffectType.Direction)
                                {
                                    animator.SetTrigger("SemiCircleToCircle");
                                }
                            }
                            entity.DirectionEffectType = effectType;
                        }
                    }
                }
            }
        }

        private void SetEffectColor(GameObject obj, int team)
        {
            var spriteRenderers = obj.GetComponentsInChildren<SpriteRenderer>(true);
            if (spriteRenderers != null)
            {
                foreach (var sprite in spriteRenderers)
                {
                    if (team == (int)MarchTeam.Self)
                    {
                        sprite.color = MarchHelper.BattleDirectionColor[0];
                    }
                    else
                    {
                        sprite.color = MarchHelper.BattleDirectionColor[1];
                    }
                }
            }
        }
        private void UpdateDirectionEffect()
        {
            if (marchManager.marchContext.MarchLodLevel < WorldEntry.MaxShowMarchLodLevel)
            {
                foreach (var entity in _haveDirectionEffectEntityList)
                {
                    if (entity.DirectionEffectObj != null)
                    {
                        if (entity.DirectionEffectType != DirectionEffectType.None)
                        {
                            var marchTarget = entity.GetTarget();
                            MarchEntity target;
                            if (marchTarget != null)
                            {
                                target = marchTarget;
                            }
                            else
                            {
                                target = entity.GetBattleTarget();
                            }
                            if (target != null)
                            {
                                entity.DirectionEffectObj.transform.forward = (target.Position - entity.Position).normalized;
                            }
                            entity.DirectionEffectObj.transform.position = entity.Position;
                        }
                    }
                }
            }
        }
        public void Dispose()
        {
            foreach (var skill in skillList)
            {
                RTSClassPoolManager.RecoverSkill(skill);
            }
            skillList.Clear();
            foreach (var attackHit in attackHitList)
            {
                RTSClassPoolManager.RecoverAttackHit(attackHit);
            }
            attackHitList.Clear();

            foreach (var skillHit in skillHitList)
            {
                RTSClassPoolManager.RecoverSkillHit(skillHit);
            }
            skillHitList.Clear();

            foreach (var skillName in skillNameList)
            {
                RTSClassPoolManager.RecoverSkillName(skillName);
            }
            skillNameList.Clear();

            marchManager = null;
            _rtsResMgr = null;

            Inst = null;
        }
        private int MarchLodLevel;
        internal void UpdateLodLevel(MarchContext marchContext)
        {

            if (MarchLodLevel == WorldEntry.MaxShowMarchLodLevel - 1 && marchManager.marchContext.MarchLodLevel == WorldEntry.MaxShowMarchLodLevel)
            {
                if (_haveDirectionEffectEntityList.Count > 0)
                {
                    foreach (var entity in _haveDirectionEffectEntityList)
                    {
                        if (entity.DirectionEffectObj != null)
                        {
                            entity.DirectionEffectObj.SetActive(false);
                        }
                    }
                }
            }
            else if (MarchLodLevel == WorldEntry.MaxShowMarchLodLevel && marchManager.marchContext.MarchLodLevel == WorldEntry.MaxShowMarchLodLevel - 1)
            {
                if (_haveDirectionEffectEntityList.Count > 0)
                {
                    foreach (var entity in _haveDirectionEffectEntityList)
                    {
                        if (entity.DirectionEffectObj != null)
                        {
                            entity.DirectionEffectObj.SetActive(true);
                        }
                    }
                }
            }

            MarchLodLevel = marchContext.MarchLodLevel;
        }
    }
}
